#include "format.h"
#include <iostream>
#include <thread>
#include "tools.h"
using namespace std;
extern "C"
{
#include <libavformat/avformat.h>
}

namespace lcf
{

    static int TimeoutCallback(void *para)
    {
        auto xf = (Format *)para;
        return (xf->IsTimeout()) ? 1 : 0;
    }

    void Format::SetContext(AVFormatContext *context)
    {
        unique_lock<mutex> lock(mtx_);
        if (context_) // 清理原值
        {
            if (context_->oformat) // 输出上下文
            {
                if (context_->pb)
                {
                    avio_closep(&context_->pb);
                }
                avformat_free_context(context_);
            }
            else if (context_->iformat) // 输入上下文
            {
                avformat_close_input(&context_);
            }
            else
            {
                avformat_free_context(context_);
            }
        }
        context_ = context;
        if (!context_)
        {
            isConnected_ = false;
            return;
        }
        isConnected_ = true;

        // 计时 用于超时判断
        lastTime_ = NowMs();

        // 设定超时处理回调
        if (timeOutMs_ > 0)
        {
            AVIOInterruptCB cb = {TimeoutCallback, this};
            context_->interrupt_callback = cb;
        }

        // 用于区分是否有音频或者视频流
        audioIndex_ = -1;
        videoIndex_ = -1;
        // 区分音视频stream 索引
        for (int i = 0; i < context->nb_streams; i++)
        {
            // 音频
            if (context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
            {
                audioIndex_ = i;
                audioTimeBase_.den = context->streams[i]->time_base.den;
                audioTimeBase_.num = context->streams[i]->time_base.num;
            }
            else if (context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
            {
                videoIndex_ = i;
                videoTimeBase_.den = context->streams[i]->time_base.den;
                videoTimeBase_.num = context->streams[i]->time_base.num;
                videoCodecId_ = context->streams[i]->codecpar->codec_id;
            }
        }
    }

    std::shared_ptr<ParameterManager> Format::CopyAudioPara()
    {
        int index = AudioIndex();
        shared_ptr<ParameterManager> re;
        unique_lock<mutex> lock(mtx_);
        if (index < 0 || !context_)
            return re;

        re.reset(ParameterManager::Create());
        *re->timeBase = context_->streams[index]->time_base;
        avcodec_parameters_copy(re->para, context_->streams[index]->codecpar);
        // 转换成毫秒
        re->totalMs = av_rescale_q(context_->streams[index]->duration,
                                   context_->streams[index]->time_base, {1, 1000});

        return re;
    }

    std::shared_ptr<ParameterManager> Format::CopyVideoPara()
    {
        int index = VideoIndex();
        shared_ptr<ParameterManager> re;
        std::unique_lock<std::mutex> lock(mtx_);
        if (index < 0 || !context_)
            return re;

        re.reset(ParameterManager::Create());
        *re->timeBase = context_->streams[index]->time_base;
        avcodec_parameters_copy(re->para, context_->streams[index]->codecpar);

        // 转换成毫秒
        re->totalMs = av_rescale_q(context_->streams[index]->duration,
                                   context_->streams[index]->time_base, {1, 1000});

        return re;
    }
    /*
    bool Format::CopyPara(int streamIndex, AVCodecContext *dts)
    {
        unique_lock<mutex> lock(mtx_);
        if (!context_)
        {
            return false;
        }
        if (streamIndex < 0 || streamIndex > context_->nb_streams)
            return false;
        auto re = avcodec_parameters_copy(dts, context_->streams[streamIndex]->codecpar);
        if (re < 0)
        {
            return false;
        }
        return true;
    }
    */

    /// 复制参数 线程安全
    bool Format::CopyPara(int streamIndex, AVCodecParameters *dts)
    {
        unique_lock<mutex> lock(mtx_);
        if (!context_)
        {
            return false;
        }
        if (streamIndex < 0 || streamIndex > context_->nb_streams)
            return false;
        auto re = avcodec_parameters_copy(dts, context_->streams[streamIndex]->codecpar);
        if (re < 0)
        {
            return false;
        }
        return true;
    }
    // 把pts dts duration 值转为毫秒
    long long Format::RescaleToMs(long long pts, int index)
    {
        unique_lock<mutex> lock(mtx_);
        if (!context_ || index < 0 || index > context_->nb_streams)
            return 0;
        auto inTimeBase = context_->streams[index]->time_base;

        AVRational outTimeBase = {1, 1000}; // timebase 毫秒
        return av_rescale_q(pts, inTimeBase, outTimeBase);
    }
    bool Format::RescaleTime(AVPacket *pkt, long long offsetPts, AVRational *timeBase)
    {
        if (!pkt || !timeBase)
            return false;
        unique_lock<mutex> lock(mtx_);
        if (!context_)
            return false;
        auto outStream = context_->streams[pkt->stream_index];
        pkt->pts = av_rescale_q_rnd(pkt->pts - offsetPts, *timeBase,
                                    outStream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
        pkt->dts = av_rescale_q_rnd(pkt->dts - offsetPts, *timeBase,
                                    outStream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
        pkt->duration = av_rescale_q(pkt->duration, *timeBase, outStream->time_base);
        pkt->pos = -1;
        return true;
    }
    bool Format::RescaleTime(AVPacket *pkt, long long offsetPts, XRational timeBase)
    {
        AVRational inTimeBase;
        inTimeBase.num = timeBase.num;
        inTimeBase.den = timeBase.den;
        return RescaleTime(pkt, offsetPts, &inTimeBase);
    }

    // 设定超时时间
    void Format::SetTimeOutMs(int ms)
    {
        unique_lock<mutex> lock(mtx_);
        timeOutMs_ = ms;
        // 设置回调函数，处理超时退出
        if (context_)
        {
            AVIOInterruptCB cb = {TimeoutCallback, this};
            context_->interrupt_callback = cb;
        }
    }

}
